home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Mark Pilgrim / Lose Your Marbles! 1.0 / source / Shell ƒ / prefs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-30  |  12.4 KB  |  447 lines  |  [TEXT/KAHL]

  1. /**********************************************************************\
  2.  
  3. File:        prefs.c
  4.  
  5. Purpose:    This module handles creating/opening/closing/updating
  6.             the preference file, and copying the preference file
  7.             data into application globals (and back).
  8.  
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program in a file named "GNU General Public License".
  21. If not, write to the Free Software Foundation, 675 Mass Ave,
  22. Cambridge, MA 02139, USA.
  23.  
  24. \**********************************************************************/
  25.  
  26. #include "program globals.h"
  27. #include "prefs.h"
  28. #include "help.h"
  29. #include "dialogs.h"
  30. #include "environment.h"
  31. #include "util.h"
  32. #include "sounds.h"
  33. #include "Folders.h"
  34.  
  35. #define        PREFS_FILE_NAME            "\pLose Your Marbles! prefs"
  36. #define        PREFS_TYPE                'pref'
  37. // CREATOR is #defined in "program globals.h"
  38. #define        PREFS_HEADER_VERSION    1
  39.  
  40. Boolean            gCanSavePrefs;
  41. Str255            gMyName;
  42. Str255            gMyOrg;
  43.  
  44. typedef struct
  45. {
  46.     long            fileID;
  47.     short            maintopic;
  48.     short            subtopic;
  49.     
  50.     char            regname[40];
  51.     char            regorg[40];
  52.     unsigned char    sound;
  53.     unsigned char    unused;
  54.     short            numrows;
  55.     short            numcolumns;
  56. } PrefStruct;
  57.  
  58. /* internal globals for use in prefs.c only */
  59. static long            gFileID;
  60. static Boolean        gCanSavePrefs;
  61. static PrefStruct    thePrefs;
  62. static long            gPrefsFilePos;
  63.  
  64. /*-----------------------------------------------------------------------------------*/
  65. /* internal stuff for prefs.c                                                        */
  66.  
  67. enum PrefErrorTypes OpenPrefsFile(short *prefsFileID);
  68. enum PrefErrorTypes SetupNewPrefsFile(short prefsFileID);
  69. void ClosePrefsFile(short prefsFileID);
  70. enum PrefErrorTypes GetNextPrefs(short prefsFileID);
  71. enum PrefErrorTypes SavePrefs(short prefsFileID);
  72. enum PrefErrorTypes CheckVersion(short prefsFileID);
  73. enum PrefErrorTypes GetFileID(void);
  74. enum PrefErrorTypes CheckFileID(void);
  75. enum PrefErrorTypes Virgin(short prefsFileID);
  76. void DefaultPrefs(void);
  77. void CopyGlobalsToPrefs(void);
  78. void CopyPrefsToGlobals(void);
  79. void GetRegistration(void);
  80.  
  81. void SaveThePrefs(void)
  82. /* standard procedure callable from anywhere to save prefs to disk (if possible) */
  83. {
  84.     short            prefsFileID;
  85.     
  86.     if (gCanSavePrefs)        /* if we had no errors in PreferencesInit() */
  87.     {
  88.         OpenPrefsFile(&prefsFileID);    /* open the prefs file */
  89.         CopyGlobalsToPrefs();            /* copy global variables to prefs struct */
  90.         SavePrefs(prefsFileID);            /* save prefs to disk */
  91.         ClosePrefsFile(prefsFileID);    /* close prefs file */
  92.     }
  93. }
  94.  
  95. enum PrefErrorTypes PreferencesInit(void)
  96. {
  97.     short            prefsFileID;
  98.     enum PrefErrorTypes        err;
  99.     
  100.     gCanSavePrefs=FALSE;    /* assume the worst and maybe you'll be pleasantly surprised */
  101.     err=GetFileID();        /* get application file ID */
  102.     if (err!=prefs_allsWell)    /* screwed up already?!? */
  103.         return err;
  104.     
  105.     err=OpenPrefsFile(&prefsFileID);    /* open prefs file (or create new one) */
  106.     if (err!=prefs_allsWell)
  107.     {
  108.         if ((err==prefs_diskReadErr) || (err==prefs_diskWriteErr) || (err==prefs_virginErr))
  109.             ClosePrefsFile(prefsFileID);    /* close & abort if error or if new prefs */
  110.         return err;
  111.     }
  112.     
  113.     err=CheckVersion(prefsFileID);        /* check prefs version */
  114.     if (err!=prefs_allsWell)
  115.     {
  116.         ClosePrefsFile(prefsFileID);
  117.         return err;
  118.     }
  119.     
  120.     GetFPos(prefsFileID, &gPrefsFilePos);
  121.     gPrefsFilePos-=sizeof(thePrefs);
  122.     do
  123.     {
  124.         gPrefsFilePos+=sizeof(thePrefs);
  125.         err=GetNextPrefs(prefsFileID);        /* get prefs struct from file */
  126.         if (err==prefs_noMorePrefsErr)        /* or not */
  127.             return (Virgin(prefsFileID));    /* can't find our file ID, it's our first time */
  128.         
  129.         if (err!=prefs_allsWell)            /* any other error, just abort */
  130.         {
  131.             ClosePrefsFile(prefsFileID);
  132.             return err;
  133.         }
  134.         
  135.         err=CheckFileID();                    /* check file ID of current prefs struct */
  136.     }
  137.     while (err==prefs_IDNotMatchErr);
  138.     
  139.     CopyPrefsToGlobals();                    /* copy prefs struct to program globals */
  140.     ClosePrefsFile(prefsFileID);            /* close prefs file */
  141.     
  142.     return prefs_allsWell;                    /* piece o' cake */
  143. }
  144.  
  145. void PrefsError(enum PrefErrorTypes err)
  146. {
  147.     Str255            tempStr;
  148.     
  149.     switch (err)
  150.     {
  151.         case prefs_diskReadErr:
  152.         case prefs_diskWriteErr:
  153.         case prefs_cantCreatePrefsErr:
  154.         case prefs_cantOpenPrefsErr:
  155.         case prefs_versionNotSupportedErr:
  156.             DefaultPrefs();                    /* use default prefs if error */
  157.             gCanSavePrefs=FALSE;            /* don't bother trying to save prefs later */
  158.             GetIndString(tempStr, 128, err);    /* get error string from .rsrc file */
  159.             ParamText(tempStr, "\p", "\p", "\p");
  160.             PositionDialog('ALRT', largeAlert);
  161.             StopAlert(largeAlert, 0L);        /* display error alert */
  162.             break;
  163.         default:
  164.             gCanSavePrefs=TRUE;                /* can save prefs to disk later if needed */
  165.             break;
  166.     }
  167. }
  168.  
  169. enum PrefErrorTypes OpenPrefsFile(short *prefsFileID)
  170. {
  171.     short            thisFile;
  172.     OSErr            isHuman;
  173.     short            vRefNum;
  174.     long            dirID;
  175.     FSSpec            prefsFile;
  176.     FInfo            prefsInfo;
  177.     Boolean            newPrefs;
  178.     unsigned char    *name=PREFS_FILE_NAME;
  179.     
  180.     newPrefs=FALSE;
  181.     /* find vRefNum and dirID of preferences folder, creating it if necessary */
  182.     isHuman=FindFolder(kOnSystemDisk, 'pref', kCreateFolder, &vRefNum, &dirID);
  183.     
  184.     if (isHuman!=noErr)        /* screwed up already?!? */
  185.         return prefs_cantOpenPrefsErr;
  186.     if (gHasFSSpecs)
  187.     {
  188.         isHuman=FSMakeFSSpec(vRefNum, dirID, name, &prefsFile);    /* make FSSpec out of it */
  189.         if (isHuman!=noErr)
  190.         {
  191.             if (isHuman==fnfErr)    /* FSSpec is valid, but prefs file does not exist */
  192.             {
  193.                 isHuman=FSpCreate(&prefsFile, CREATOR, PREFS_TYPE, 0);    /* so create it */
  194.                 if (isHuman!=noErr)                                        /* or not */
  195.                     return prefs_cantCreatePrefsErr;
  196.                 newPrefs=TRUE;        /* signal that prefs file is new */
  197.             }
  198.             else return prefs_cantOpenPrefsErr;
  199.         }
  200.         isHuman=FSpOpenDF(&prefsFile, fsRdWrPerm, &thisFile);    /* open prefs file */
  201.         *prefsFileID=thisFile;        /* store file reference number */
  202.         if (isHuman!=noErr)
  203.             return prefs_cantOpenPrefsErr;
  204.     }
  205.     else
  206.     {
  207.         /* try to open prefs file */
  208.         isHuman=HOpen(vRefNum, dirID, name, fsRdWrPerm, &thisFile);
  209.         *prefsFileID=thisFile;
  210.         if (isHuman!=noErr)
  211.         {
  212.             if (isHuman==fnfErr)    /* prefs file does not exist */
  213.             {
  214.                 /* ...so create it */
  215.                 if (HCreate(vRefNum, dirID, name, CREATOR, PREFS_TYPE)!=noErr)
  216.                     return prefs_cantCreatePrefsErr;
  217.                 prefsInfo.fdType=PREFS_TYPE;
  218.                 prefsInfo.fdCreator=CREATOR;
  219.                 prefsInfo.fdFlags=0;
  220.                 prefsInfo.fdLocation.h=prefsInfo.fdLocation.v=0;
  221.                 prefsInfo.fdFldr=0;
  222.                 
  223.                 /* set file info of newly created prefs file */
  224.                 if (HSetFInfo(vRefNum, dirID, name, &prefsInfo)!=noErr)
  225.                     return prefs_cantCreatePrefsErr;
  226.                 
  227.                 /* NOW open the prefs file */
  228.                 isHuman=HOpen(vRefNum, dirID, name, fsRdWrPerm, &thisFile);
  229.                 *prefsFileID=thisFile;        /* store file reference number */
  230.                 if (isHuman!=noErr)
  231.                     return prefs_cantOpenPrefsErr;
  232.                 newPrefs=TRUE;                /* signal that prefs file is new */
  233.             }
  234.             else return prefs_cantOpenPrefsErr;
  235.         }
  236.     }
  237.     if (newPrefs)
  238.         return SetupNewPrefsFile(*prefsFileID);        /* needs initial setup if new */
  239.     
  240.     return prefs_allsWell;
  241. }
  242.  
  243. enum PrefErrorTypes SetupNewPrefsFile(short prefsFileID)
  244. /* this writes the prefs version number to the newly created prefs file, so we can
  245.    tell if the prefs file was created by a later version of the program and is
  246.    therefore in a format that we don't support -- forward compatability!  what
  247.    a concept! */
  248. {
  249.     long            count;
  250.     short            temp;
  251.     
  252.     gPrefsFilePos=2L;
  253.     if (SetEOF(prefsFileID, 2L)!=noErr)    /* set length of prefs file to 2 */
  254.         return prefs_diskWriteErr;
  255.     
  256.     SetFPos(prefsFileID, 1, 0L);
  257.     temp=PREFS_HEADER_VERSION;            /* get the prefs version (hardcoded) */
  258.     count=2L;
  259.     if (FSWrite(prefsFileID, &count, &temp)!=noErr)        /* write prefs version */
  260.         return prefs_diskWriteErr;        
  261.     
  262.     return Virgin(prefsFileID);            /* be gentle; it's our first time */
  263. }
  264.  
  265. void ClosePrefsFile(short prefsFileID)
  266. {
  267.     FSClose(prefsFileID);                /* close file on disk */
  268.     FlushVol(0L, kOnSystemDisk);        /* flush volume to write out new info */
  269. }
  270.  
  271. enum PrefErrorTypes GetNextPrefs(short prefsFileID)
  272. {
  273.     OSErr        isHuman;
  274.     long        count;
  275.     
  276.     count=sizeof(thePrefs);
  277.     isHuman=FSRead(prefsFileID, &count, &thePrefs);        /* get next prefs struct */
  278.     if (isHuman==eofErr)    /* no more left */
  279.         return prefs_noMorePrefsErr;
  280.     if (isHuman!=noErr)        /* some other error */
  281.         return prefs_diskReadErr;
  282.     
  283.     return prefs_allsWell;
  284. }
  285.  
  286. enum PrefErrorTypes SavePrefs(short prefsFileID)
  287. {
  288.     long        oldEOF;
  289.     long        count;
  290.     
  291.     GetEOF(prefsFileID, &oldEOF);
  292.     if (gPrefsFilePos>=oldEOF)        /* add new prefs struct onto end of prefs file */
  293.     {
  294.         if (SetEOF(prefsFileID, oldEOF+sizeof(thePrefs))!=noErr)
  295.             return prefs_diskWriteErr;
  296.     }
  297.     
  298.     SetFPos(prefsFileID, 1, gPrefsFilePos);        /* set position inside prefs file */
  299.     count=sizeof(thePrefs);
  300.     /* write prefs struct and return appropriate error code */
  301.     return (FSWrite(prefsFileID, &count, &thePrefs)!=noErr) ?
  302.         prefs_diskWriteErr : prefs_allsWell;
  303. }
  304.  
  305. enum PrefErrorTypes CheckVersion(short prefsFileID)
  306. {
  307.     OSErr        isHuman;
  308.     long        count;
  309.     short            temp;
  310.     
  311.     count=2L;
  312.     isHuman=FSRead(prefsFileID, &count, &temp);        /* get prefs version */
  313.     if (isHuman!=noErr)
  314.         return prefs_diskReadErr;
  315.     if (temp>PREFS_HEADER_VERSION)                    /* too new */
  316.         return prefs_versionNotSupportedErr;
  317.     if (temp<PREFS_HEADER_VERSION)                    /* old; overwrite */
  318.         return SetupNewPrefsFile(prefsFileID);
  319.     
  320.     return prefs_allsWell;
  321. }
  322.  
  323. enum PrefErrorTypes GetFileID(void)
  324. {
  325.     ParamBlockRec    pb;
  326.     
  327.     pb.fileParam.ioCompletion=0L;
  328.     pb.fileParam.ioNamePtr=CurApName;
  329.     pb.fileParam.ioVRefNum=0;
  330.     pb.fileParam.ioFVersNum=0;
  331.     pb.fileParam.ioFDirIndex=0;
  332.     if (PBGetFInfo(&pb, FALSE)!=noErr)
  333.         return prefs_diskReadErr;
  334.     
  335.     gFileID=pb.fileParam.ioFlNum;
  336. }
  337.  
  338. enum PrefErrorTypes CheckFileID(void)
  339. {
  340.     /* compare file ID in current prefs struct to application's file ID */
  341.     return (thePrefs.fileID==gFileID) ? prefs_allsWell : prefs_IDNotMatchErr;
  342. }
  343.  
  344. enum PrefErrorTypes Virgin(short prefsFileID)
  345. {
  346.     short            err;
  347.     
  348.     DefaultPrefs();
  349.     CopyGlobalsToPrefs();
  350.     err=SavePrefs(prefsFileID);
  351.     if (err!=prefs_allsWell)
  352.         return err;
  353.     DoSound(sound_virgin, TRUE);
  354.     GetRegistration();
  355.     CopyGlobalsToPrefs();
  356.     err=SavePrefs(prefsFileID);
  357.     
  358.     return (err==prefs_allsWell) ? prefs_virginErr : err;
  359. }
  360.  
  361. void DefaultPrefs(void)
  362. {
  363.     unsigned char        *bob="\pBob";
  364.     
  365.     Mymemcpy((Ptr)gMyName, (Ptr)bob, bob[0]+1);
  366.     gMyOrg[0]=0x00;
  367.     gSoundToggle=0xFF;
  368.     gNumRows=5;
  369.     gNumColumns=5;
  370.     gMainTopicShowing=gSubTopicShowing=0;
  371. }
  372.  
  373. void CopyGlobalsToPrefs(void)
  374. {
  375.     Mymemset((Ptr)(&thePrefs), 0, sizeof(thePrefs));
  376.     if (gMyName[0]>0x27)
  377.         gMyName[0]=0x27;
  378.     if (gMyOrg[0]>0x27)
  379.         gMyOrg[0]=0x27;
  380.     Mymemcpy((Ptr)thePrefs.regname, (Ptr)gMyName, gMyName[0]+1);
  381.     Mymemcpy((Ptr)thePrefs.regorg, (Ptr)gMyOrg, gMyOrg[0]+1);
  382.     thePrefs.maintopic=gMainTopicShowing;
  383.     thePrefs.subtopic=gSubTopicShowing;
  384.     thePrefs.fileID=gFileID;
  385.     
  386.     thePrefs.sound=gSoundToggle;
  387.     thePrefs.numrows=gNumRows;
  388.     thePrefs.numcolumns=gNumColumns;
  389. }
  390.  
  391. void CopyPrefsToGlobals(void)
  392. {
  393.     Mymemcpy((Ptr)gMyName, (Ptr)thePrefs.regname, thePrefs.regname[0]+1);
  394.     Mymemcpy((Ptr)gMyOrg, (Ptr)thePrefs.regorg, thePrefs.regorg[0]+1);
  395.     gMainTopicShowing=thePrefs.maintopic;
  396.     gSubTopicShowing=thePrefs.subtopic;
  397.     
  398.     gSoundToggle=thePrefs.sound;
  399.     gNumRows=thePrefs.numrows;
  400.     gNumColumns=thePrefs.numcolumns;
  401. }
  402.  
  403. void GetRegistration(void)
  404. {
  405.     DialogPtr        theDlog;
  406.     short            itemSelected = 0;
  407.     short            newleft;
  408.     short            newtop;
  409.     short            itemType;
  410.     Handle            item;
  411.     Rect            box;
  412.     
  413.     theDlog = GetNewDialog(personalDialog, 0L, (WindowPtr)-1L);
  414.     newleft = screenBits.bounds.left + (((screenBits.bounds.right -
  415.                 screenBits.bounds.left) - (theDlog->portRect.right -
  416.                 theDlog->portRect.left)) / 2);
  417.     newtop = screenBits.bounds.top + (((screenBits.bounds.bottom -
  418.                 screenBits.bounds.top) - (theDlog->portRect.bottom -
  419.                 theDlog->portRect.top)) / 2);
  420.     if(newtop < 15)
  421.         newtop = 15;
  422.     GetDItem(theDlog, 1, &itemType, &item, &box);
  423.     InsetRect(&box, -4, -4);
  424.     SetDItem(theDlog, 8, userItem, (ProcPtr)OutlineDefaultButton, &box);
  425.     ParamText(APPLICATION_NAME, "\p", "\p", "\p");
  426.     
  427.     MoveWindow(theDlog, newleft, newtop, TRUE);
  428.     ShowWindow(theDlog);
  429.     while(itemSelected != 1)
  430.     {
  431.         ModalDialog(0L, &itemSelected);
  432.     }
  433.     GetDItem(theDlog,4,&itemType,&item,&box);
  434.     GetIText(item,gMyName);
  435.     
  436.     GetDItem(theDlog,5,&itemType,&item,&box);
  437.     GetIText(item,gMyOrg);
  438.  
  439.     if (gMyName[0]==0x00)
  440.         DefaultPrefs();
  441.  
  442.     HideWindow(theDlog);
  443.     DisposeDialog(theDlog);
  444.     
  445.     gIsVirgin=TRUE;
  446. }
  447.